iT邦幫忙

2025 iThome 鐵人賽

DAY 29
0

前言

隨著網站的功能擴充,越來越多支的 Amazon Lambda Function 的出現,管理上變得有些複雜。 除了 Lambda 本身的 Source Code 外,還有各個 Lambda Function 使用的 IAM Roles / Policies 分別設定了不同的權限並允許各自可以觸及的範圍。 除此之外,一些在等待 DynamoDB 存取的程式,需要運行比較長的秒數,也有對應的設定喔。

前置作業

  • 在 MacOS 上安裝 Terraform
brew install terraform
  • 確定 aws cli 已經可以正常運作 / 或者是初始化設定 credentials
aws configure
  • 測試設定是否成功
aws sts get-caller-identity
  • 建議安裝 VSCode 後,順便裝個 HashiCorp Terraform 套件,以利後續管理原始碼。

IaC / Terraform

專案結構

  • 預計規劃的專案如下
vlog-infra/
 ├── main.tf
 ├── variables.tf
 ├── outputs.tf
 ├── lambda/
 │   ├── list_vlog_videos/
 │   │   ├── main.py
 │   │   └── requirements.txt
 │   ├── register_vlog_member/
 │   │   ├── main.py
 │   │   └── requirements.txt
 │   └── ...

main.tf

  • 接著要來撰寫 main.tf,用來描述我們的基礎設施,集中收納 AWS 上的一些通用資源。
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  required_version = ">= 1.5.0"
}

provider "aws" {
  region = "ap-northeast-1"
}

# 🔹 IAM Role for Lambda
resource "aws_iam_role" "lambda_exec" {
  name = "lambda-execution-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = { Service = "lambda.amazonaws.com" }
      Action = "sts:AssumeRole"
    }]
  })
}

# 🔹 IAM Policy 附加 (讓 Lambda 能使用 S3 / DynamoDB / SES)
resource "aws_iam_role_policy" "lambda_policy" {
  name = "lambda-execution-policy"
  role = aws_iam_role.lambda_exec.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Action = [
          "logs:*",
          "s3:*",
          "dynamodb:*",
          "ses:SendEmail"
        ],
        Resource = "*"
      }
    ]
  })
}

# 🔹 Lambda Function (list-vlog-videos)
resource "aws_lambda_function" "list_vlog_videos" {
  function_name = "list-vlog-videos"
  role          = aws_iam_role.lambda_exec.arn
  handler       = "main.lambda_handler"
  runtime       = "python3.13"

  filename         = "lambda/list_vlog_videos.zip"
  source_code_hash = filebase64sha256("lambda/list_vlog_videos.zip")

  environment {
    variables = {
      BUCKET_NAME = "exsky-backup-media"
      JWT_SECRET  = "mysecret"
    }
  }
}

# 🔹 API Gateway (HTTP API)
resource "aws_apigatewayv2_api" "vlog_api" {
  name          = "vlog-api"
  protocol_type = "HTTP"
}

# 🔹 Lambda Integration
resource "aws_apigatewayv2_integration" "list_videos_integration" {
  api_id                 = aws_apigatewayv2_api.vlog_api.id
  integration_type       = "AWS_PROXY"
  integration_uri        = aws_lambda_function.list_vlog_videos.invoke_arn
  payload_format_version = "2.0"
}

# 🔹 路由 (GET /list-videos)
resource "aws_apigatewayv2_route" "list_videos_route" {
  api_id    = aws_apigatewayv2_api.vlog_api.id
  route_key = "GET /list-videos"
  target    = "integrations/${aws_apigatewayv2_integration.list_videos_integration.id}"
}

# 🔹 API 部署
resource "aws_apigatewayv2_stage" "prod" {
  api_id      = aws_apigatewayv2_api.vlog_api.id
  name        = "prod"
  auto_deploy = true
}

# 🔹 允許 API Gateway 呼叫 Lambda
resource "aws_lambda_permission" "apigw_invoke" {
  statement_id  = "AllowAPIGatewayInvoke"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.list_vlog_videos.function_name
  principal     = "apigateway.amazonaws.com"
  source_arn    = "${aws_apigatewayv2_api.vlog_api.execution_arn}/*/*"
}

output "api_endpoint" {
  value = aws_apigatewayv2_stage.prod.invoke_url
}

匯出 / 打包 Lambda Function

走 UI 匯出

  • 先到 AWS Console / Lambda Console / Functions / 選擇你的函式
  • 點選右上角 Download / Download function code .zip
  • 解壓縮後你會看到:
    • lambda_function.py
    • requirements.txt (不一定會有)
  • 接著就可以將這份 ZIP 放入你的 IaC 專案中管理。

走 AWS CLI 匯出

  • 用下列指令,會得到一條暫時可以下載的連結,用來下載 deployment package (.zip)
mkdir -p lambda
cd lambda

# 把所有的 Vlog 相關的 Function 都載下來,這邊用一支 list-vlog-videos 當作範例
aws lambda get-function --function-name list-vlog-videos --query 'Code.Location' --output text | xargs curl -o list-vlog-videos.zip

# 其他還有 ... (截至今日,共 14 支)
reset-vlog-password
forgot-vlog-password
register-vlog-member
verify-vlog-email
generate-vlog-cover
prompt-vlog-reel
generate-vlog-subtitle
delete-vlog-video
convert-vlog-mov-to-mp4
list-vlog-subtitles
generate-vlog-s3-presigned-url
validate-vlog-member
login-vlog-member

完成 main.tf

  • Lambda Function 原始碼要先打包成 ZIP 才能被 Terraform 部署。
  • 根據上面規劃的專案目錄,我們預計在 vlog-infra 下,新增一個 lambda 目錄專門收容各個 Lambda。
  • 在上面 main.tf 中寫了 ...
# 🔹 Lambda Function (list-vlog-videos)
resource "aws_lambda_function" "list_vlog_videos" {
  function_name = "list-vlog-videos"
  role          = aws_iam_role.lambda_exec.arn
  handler       = "main.lambda_handler"
  runtime       = "python3.13"

  filename         = "lambda/list_vlog_videos.zip"
  source_code_hash = filebase64sha256("lambda/list_vlog_videos.zip")

  environment {
    variables = {
      BUCKET_NAME = "exsky-backup-media"
      JWT_SECRET  = "mysecret"
    }
  }
}

  • 其中有指定 filename = "lambda/list_vlog_videos.zip"
    • 這是用來指定匯入原始碼檔案的來源
  • 所以,類似的結構要做 14 段,分別用來指定 14 支 Fucntion

部署!

terraform init
terraform plan
terraform apply

結論

  • 最近因為實在太忙,可以預計完賽後要休息一陣子,到時候回頭繼續改的時候,會需要花一些時間重新熟悉先前做的內容。
  • 如果可以進行版本控制,透過 git 或是 terraform 來管理的話,那就可以大幅降低回想的時間。

上一篇
【Day 28】 限制會員存放容量上限 (下)
下一篇
【Day 30】 修改 Terraform / 託管既存的 API Gateway 資源
系列文
無法成為片師也想拍 Vlog?!個人影音小工具的誕生!30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言